From 5a2f791bddd90f65a2d867ab1df061c3d786b6d2 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 5 Jul 2020 15:07:36 -0400 Subject: [PATCH] filefilter: Cleanups and optimizations Make mime-type rules hold multiple types. Store the content types, so we don't have to do mime-type -> content-type conversion in the match function. Store content types for the pixbuf-formats rule as well, so we can avoid memory allocation in the match function altogether. --- gtk/gtkfilefilter.c | 256 +++++++++++++++++++++++--------------------- 1 file changed, 136 insertions(+), 120 deletions(-) diff --git a/gtk/gtkfilefilter.c b/gtk/gtkfilefilter.c index e555190aa4..c2b8bb5537 100644 --- a/gtk/gtkfilefilter.c +++ b/gtk/gtkfilefilter.c @@ -108,8 +108,8 @@ struct _FilterRule FilterRuleType type; union { - gchar *pattern; - gchar *mime_type; + char *pattern; + char **content_types; GSList *pixbuf_formats; } u; }; @@ -200,14 +200,12 @@ filter_rule_free (FilterRule *rule) { switch (rule->type) { - case FILTER_RULE_MIME_TYPE: - g_free (rule->u.mime_type); - break; case FILTER_RULE_PATTERN: g_free (rule->u.pattern); break; + case FILTER_RULE_MIME_TYPE: case FILTER_RULE_PIXBUF_FORMATS: - g_slist_free (rule->u.pixbuf_formats); + g_strfreev (rule->u.content_types); break; default: g_assert_not_reached (); @@ -541,16 +539,17 @@ file_filter_add_attribute (GtkFileFilter *filter, **/ void gtk_file_filter_add_mime_type (GtkFileFilter *filter, - const gchar *mime_type) + const gchar *mime_type) { FilterRule *rule; - + g_return_if_fail (GTK_IS_FILE_FILTER (filter)); g_return_if_fail (mime_type != NULL); rule = g_slice_new (FilterRule); rule->type = FILTER_RULE_MIME_TYPE; - rule->u.mime_type = g_strdup (mime_type); + rule->u.content_types = g_new0 (char *, 2); + rule->u.content_types[0] = g_content_type_from_mime_type (mime_type); file_filter_add_attribute (filter, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); file_filter_add_rule (filter, rule); @@ -594,12 +593,34 @@ void gtk_file_filter_add_pixbuf_formats (GtkFileFilter *filter) { FilterRule *rule; - + GPtrArray *array; + GSList *formats, *l; + g_return_if_fail (GTK_IS_FILE_FILTER (filter)); rule = g_slice_new (FilterRule); rule->type = FILTER_RULE_PIXBUF_FORMATS; - rule->u.pixbuf_formats = gdk_pixbuf_get_formats (); + + array = g_ptr_array_new (); + + formats = gdk_pixbuf_get_formats (); + for (l = formats; l; l = l->next) + { + int i; + char **mime_types; + + mime_types = gdk_pixbuf_format_get_mime_types (l->data); + + for (i = 0; mime_types[i] != NULL; i++) + { + g_ptr_array_add (array, g_content_type_from_mime_type (mime_types[i])); + } + } + g_slist_free (formats); + + g_ptr_array_add (array, NULL); + + rule->u.content_types = (char **)g_ptr_array_free (array, FALSE); file_filter_add_attribute (filter, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); file_filter_add_rule (filter, rule); @@ -638,61 +659,65 @@ NSArray * _gtk_file_filter_get_as_pattern_nsstrings (GtkFileFilter *filter) FilterRule *rule = tmp_list->data; switch (rule->type) - { - case FILTER_RULE_MIME_TYPE: - { - // convert mime-types to UTI - NSString *mime_type_nsstring = [NSString stringWithUTF8String: rule->u.mime_type]; - NSString *uti_nsstring = (NSString *) UTTypeCreatePreferredIdentifierForTag (kUTTagClassMIMEType, (CFStringRef) mime_type_nsstring, NULL); - if (uti_nsstring == NULL) - { - [array release]; - return NULL; - } - [array addObject:uti_nsstring]; - } - break; - case FILTER_RULE_PATTERN: - { - // patterns will need to be stripped of their leading *. - GString *pattern = g_string_new (rule->u.pattern); - if (strncmp (pattern->str, "*.", 2) == 0) - { - pattern = g_string_erase (pattern, 0, 2); - } - else if (strncmp (pattern->str, "*", 1) == 0) - { - pattern = g_string_erase (pattern, 0, 1); - } - gchar *pattern_c = g_string_free (pattern, FALSE); - NSString *pattern_nsstring = [NSString stringWithUTF8String:pattern_c]; - g_free (pattern_c); - [pattern_nsstring retain]; - [array addObject:pattern_nsstring]; - } - break; - case FILTER_RULE_PIXBUF_FORMATS: - { - GSList *list; - - for (list = rule->u.pixbuf_formats; list; list = list->next) - { - int i; - gchar **extensions; - - extensions = gdk_pixbuf_format_get_extensions (list->data); - - for (i = 0; extensions[i] != NULL; i++) - { - NSString *extension = [NSString stringWithUTF8String: extensions[i]]; - [extension retain]; - [array addObject:extension]; - } - g_strfreev (extensions); - } - break; - } - } + { + case FILTER_RULE_MIME_TYPE: + { + // convert mime-types to UTI + NSString *mime_type_nsstring = [NSString stringWithUTF8String: rule->u.content_types[0]]; + NSString *uti_nsstring = (NSString *) UTTypeCreatePreferredIdentifierForTag (kUTTagClassMIMEType, (CFStringRef) mime_type_nsstring, NULL); + if (uti_nsstring == NULL) + { + [array release]; + return NULL; + } + [array addObject:uti_nsstring]; + } + break; + + case FILTER_RULE_PATTERN: + { + // patterns will need to be stripped of their leading *. + GString *pattern = g_string_new (rule->u.pattern); + if (strncmp (pattern->str, "*.", 2) == 0) + { + pattern = g_string_erase (pattern, 0, 2); + } + else if (strncmp (pattern->str, "*", 1) == 0) + { + pattern = g_string_erase (pattern, 0, 1); + } + gchar *pattern_c = g_string_free (pattern, FALSE); + NSString *pattern_nsstring = [NSString stringWithUTF8String:pattern_c]; + g_free (pattern_c); + [pattern_nsstring retain]; + [array addObject:pattern_nsstring]; + } + break; + + case FILTER_RULE_PIXBUF_FORMATS: + { + GSList *formats, *l; + + formats = gdk_pixbuf_get_formats (); + for (l = formats; l; l = l->next) + { + int i; + gchar **extensions; + + extensions = gdk_pixbuf_format_get_extensions (l->data); + + for (i = 0; extensions[i] != NULL; i++) + { + NSString *extension = [NSString stringWithUTF8String: extensions[i]]; + [extension retain]; + [array addObject:extension]; + } + g_strfreev (extensions); + } + g_slist_free (formats); + break; + } + } } return array; } @@ -711,35 +736,39 @@ _gtk_file_filter_get_as_patterns (GtkFileFilter *filter) FilterRule *rule = tmp_list->data; switch (rule->type) - { - case FILTER_RULE_MIME_TYPE: + { + case FILTER_RULE_MIME_TYPE: g_ptr_array_free (array, TRUE); return NULL; - break; - case FILTER_RULE_PATTERN: + break; + + case FILTER_RULE_PATTERN: g_ptr_array_add (array, g_strdup (rule->u.pattern)); - break; - case FILTER_RULE_PIXBUF_FORMATS: - { - GSList *list; + break; + + case FILTER_RULE_PIXBUF_FORMATS: + { + GSList *formats, *l; - for (list = rule->u.pixbuf_formats; list; list = list->next) - { - int i; - gchar **extensions; + formats = gdk_pixbuf_get_formats (); + for (l = formats; l; l = l->next) + { + int i; + char **extensions; - extensions = gdk_pixbuf_format_get_extensions (list->data); + extensions = gdk_pixbuf_format_get_extensions (l->data); - for (i = 0; extensions[i] != NULL; i++) + for (i = 0; extensions[i] != NULL; i++) g_ptr_array_add (array, g_strdup_printf ("*.%s", extensions[i])); - g_strfreev (extensions); - } - break; - } + g_strfreev (extensions); + } + g_slist_free (formats); + break; + } default: break; - } + } } g_ptr_array_add (array, NULL); /* Null terminate */ @@ -786,39 +815,38 @@ gtk_file_filter_match (GtkFilter *filter, switch (rule->type) { - case FILTER_RULE_MIME_TYPE: + case FILTER_RULE_PATTERN: { - const char *filter_content_type; - char *rule_content_type; - gboolean match; + const char *display_name; - filter_content_type = g_file_info_get_content_type (info); - if (filter_content_type) + display_name = g_file_info_get_display_name (info); + if (display_name) { - rule_content_type = g_content_type_from_mime_type (rule->u.mime_type); - match = g_content_type_is_a (filter_content_type, rule_content_type); - g_free (rule_content_type); - - if (match) + if (_gtk_fnmatch (rule->u.pattern, display_name, FALSE)) return TRUE; } } break; - case FILTER_RULE_PATTERN: + case FILTER_RULE_MIME_TYPE: + case FILTER_RULE_PIXBUF_FORMATS: { - const char *display_name; + const char *filter_content_type; - display_name = g_file_info_get_display_name (info); - if (display_name) + filter_content_type = g_file_info_get_content_type (info); + if (filter_content_type) { - if (_gtk_fnmatch (rule->u.pattern, display_name, FALSE)) - return TRUE; + int i; + + for (i = 0; rule->u.content_types[i]; i++) + { + if (g_content_type_is_a (filter_content_type, rule->u.content_types[i])) + return TRUE; + } } } break; - case FILTER_RULE_PIXBUF_FORMATS: { const char *filter_content_type; @@ -875,32 +903,20 @@ gtk_file_filter_to_gvariant (GtkFileFilter *filter) for (l = filter->rules; l; l = l->next) { FilterRule *rule = l->data; + int i; switch (rule->type) { case FILTER_RULE_PATTERN: g_variant_builder_add (&builder, "(us)", 0, rule->u.pattern); break; + case FILTER_RULE_MIME_TYPE: - g_variant_builder_add (&builder, "(us)", 1, rule->u.mime_type); - break; case FILTER_RULE_PIXBUF_FORMATS: - { - GSList *f; - - for (f = rule->u.pixbuf_formats; f; f = f->next) - { - GdkPixbufFormat *fmt = f->data; - gchar **mime_types; - int i; - - mime_types = gdk_pixbuf_format_get_mime_types (fmt); - for (i = 0; mime_types[i]; i++) - g_variant_builder_add (&builder, "(us)", 1, mime_types[i]); - g_strfreev (mime_types); - } - } + for (i = 0; rule->u.content_types[i]; i++) + g_variant_builder_add (&builder, "(us)", 1, rule->u.content_types[i]); break; + default: break; } -- 2.30.2